package com.zjgsu.nftplatform.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zjgsu.nftplatform.client.BlockchainClient;
import com.zjgsu.nftplatform.entity.*;
import com.zjgsu.nftplatform.mapper.*;
import com.zjgsu.nftplatform.pojo.*;
import com.zjgsu.nftplatform.service.GoodsService;
import com.zjgsu.nftplatform.util.UserIdUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ahy231
 * @date 2022/3/26 21:31
 * @description
 */
@Service
public class GoodsServiceImpl implements GoodsService {

    private final GoodsMapper goodsMapper;
    private final WareMapper wareMapper;
    private final NftMapper nftMapper;
    private final FollowMapper followMapper;
    private final UserMapper userMapper;
    private final CommentMapper commentMapper;
    private final OfferMapper offerMapper;
    private final BargainMapper bargainMapper;
    private final UserWareMapper userWareMapper;

    private final BlockchainClient blockchainClient;

    public GoodsServiceImpl(GoodsMapper goodsMapper, WareMapper wareMapper, NftMapper nftMapper, FollowMapper followMapper, UserMapper userMapper, CommentMapper commentMapper, OfferMapper offerMapper, BargainMapper bargainMapper, UserWareMapper userWareMapper, BlockchainClient blockchainClient) {
        this.goodsMapper = goodsMapper;
        this.wareMapper = wareMapper;
        this.nftMapper = nftMapper;
        this.followMapper = followMapper;
        this.userMapper = userMapper;
        this.commentMapper = commentMapper;
        this.offerMapper = offerMapper;
        this.bargainMapper = bargainMapper;
        this.userWareMapper = userWareMapper;
        this.blockchainClient = blockchainClient;
    }

    @Override
    public List<Advertisement> advertisement() {
        return new ArrayList<>();
    }

    @Override
    public PageInfo<GoodsInfo> workResearch(GoodsResearch research) {
        if (research.getGoodsSearch() != null && research.getGoodsSearch().getComprehensiveOrder() != null && research.getGoodsSearch().getComprehensiveOrder()) {
            List<GoodsInfo> goodsInfos = goodsMapper.selectGoods(research);
            setStars(goodsInfos);

            Integer maxStars = goodsInfos.stream().max(Comparator.comparingInt(GoodsInfo::getStars))
                    .orElseThrow(() -> new RuntimeException("error happened when fetch max stars")).getStars();
            Date minStartTime = goodsInfos.stream().min(Comparator.comparing(GoodsInfo::getStartTime))
                    .orElseThrow(() -> new RuntimeException("error happened when fetch min start time")).getStartTime();
            goodsInfos.forEach(g -> g.setStatus(g.getStatus()));
            goodsInfos.forEach(g -> g.setComprehensiveScore(getScore(
                    new ComprehensiveInfo(g.getStars(), g.getStartTime()),
                    new ComprehensiveInfo(maxStars, minStartTime))));
            goodsInfos.sort(Comparator.comparingDouble(GoodsInfo::getComprehensiveScore));

            Integer pageNum = research.getLimit().getPageNum();
            Integer pageSize = research.getLimit().getPageSize();

            PageInfo<GoodsInfo> pageInfo;
            if (goodsInfos.size() >= pageNum * pageSize) {
                pageInfo = PageInfo.of(goodsInfos.subList((pageNum - 1) * pageSize, pageNum * pageSize));
                pageInfo.setPageNum(pageNum);
                pageInfo.setPageSize(pageSize);
                pageInfo.setPages((int) Math.ceil(goodsInfos.size() / (double) pageSize));
            } else {
                pageInfo = PageInfo.of(goodsInfos);
                pageInfo.setPageNum(1);
                pageInfo.setPageSize(goodsInfos.size());
                pageInfo.setPages(1);
            }

            return pageInfo;
        } else {
            Page<GoodsInfo> page = PageHelper.startPage(research.getLimit().getPageNum(), research.getLimit().getPageSize());
            List<GoodsInfo> goodsInfos = goodsMapper.selectGoods(research);
            goodsInfos.forEach(g -> g.setStatus(g.getStatus()));
            setStars(goodsInfos);

            return PageInfo.of(page);
        }
    }

    private void setStars(List<GoodsInfo> goodsInfos) {
        List<Long> ids = goodsInfos.stream().map(g -> Long.parseLong(g.getId())).collect(Collectors.toList());
        Map<Long, Map<String, Long>> stars = goodsMapper.selectStarCountOfWare(ids);
        goodsInfos.forEach(g -> stars.putIfAbsent(Long.parseLong(g.getId()), MapUtil.of("amount", 0L)));
        goodsInfos.forEach(g -> g.setStars(Math.toIntExact(stars.get(Long.parseLong(g.getId())).get("amount"))));
    }

    @Override
    public PageInfo<DealInfo> dealResearch(DealResearch research) {
        Integer pageNum = research.getLimit().getPageNum();
        Integer pageSize = research.getLimit().getPageSize();

        if (research.getComprehensiveOrder() != null && research.getComprehensiveOrder()) {
            List<DealInfo> dealInfos = goodsMapper.selectDeal(research);
            dealInfos.forEach(d -> {
                Long buyerId = d.getBuyerId();
                Long sellerId = d.getSellerId();
                d.setBuyerName(userMapper.selectById(buyerId).getName());
                d.setSellerName(userMapper.selectById(sellerId).getName());
            });

            // get stars
            List<Long> ids = dealInfos.stream().map(DealInfo::getWareId).collect(Collectors.toList());
            Map<Long, Map<String, Long>> stars = goodsMapper.selectStarCountOfWare(ids);

            Integer maxStars = Math.toIntExact(stars.values().stream().max(Comparator.comparingLong(s -> s.get("amount")))
                    .orElse(MapUtil.of("amount", 0L)).get("amount"));
            Date minTime = dealInfos.stream().min(Comparator.comparing(DealInfo::getEndTime))
                    .orElse(DealInfo.builder().endTime(Calendar.getInstance().getTime()).build()).getEndTime();

            dealInfos.forEach(d -> stars.putIfAbsent(d.getWareId(), MapUtil.of("amount", 0L)));

            dealInfos.forEach(d -> d.setComprehensiveScore(getScore(
                    new ComprehensiveInfo(Math.toIntExact(stars.get(d.getWareId()).get("amount")),
                            d.getEndTime() != null ? d.getEndTime() : Calendar.getInstance().getTime()),
                    new ComprehensiveInfo(maxStars, minTime)
            )));
            dealInfos.sort(Comparator.comparingDouble(DealInfo::getComprehensiveScore));

            PageInfo<DealInfo> pageInfo;
            if (dealInfos.size() == pageSize) {
                pageInfo = PageInfo.of(dealInfos.subList((pageNum - 1) * pageSize, pageNum * pageSize));
                pageInfo.setPageNum(pageNum);
                pageInfo.setPageSize(pageSize);
                pageInfo.setPages((int) Math.ceil(dealInfos.size() / (double) pageSize));
            } else {
                pageInfo = PageInfo.of(dealInfos);
                pageInfo.setPageNum(1);
                pageInfo.setPageSize(dealInfos.size());
                pageInfo.setPages(1);
            }

            return pageInfo;
        } else {
            Page<DealInfo> page = PageHelper.startPage(pageNum, pageSize);
            List<DealInfo> dealInfos = goodsMapper.selectDeal(research);
            dealInfos.forEach(d -> {
                Long buyerId = d.getBuyerId();
                Long sellerId = d.getSellerId();
                d.setBuyerName(userMapper.selectById(buyerId).getName());
                d.setSellerName(userMapper.selectById(sellerId).getName());
            });
            return PageInfo.of(page);
        }
    }

    @Override
    public List<GoodsDetail> goodsDetail(Long nftId) {
        List<Ware> wareList = wareMapper.selectList(new QueryWrapper<Ware>().eq("nft_id", nftId));
        ArrayList<GoodsDetail> result = new ArrayList<>();

        Nft nft = nftMapper.selectById(nftId);
        if(wareList == null || wareList.size() < 1){
            GoodsDetail goodsDetail = GoodsDetail.builder()
                    .nftId(nftId.toString())
                    .name(nft.getName())
                    .img(nft.getImg())
                    .attributes(nft.getAttribute())
                    .views(nft.getViews() + 1)
                    .author(nft.getUsername())
                    .authorId(nft.getUserId().toString())
                    .owner(nft.getOwnerName())
                    .ownerId(nft.getOwnerId().toString())
                    .chainAddress(nft.getChainAddress())
                    .description(nft.getDescription())
                    .build();

            result.add(goodsDetail);
        }else {
            for (Ware ware : wareList) {
                Map<Long, Map<String, Long>> starCountOfWare = goodsMapper.selectStarCountOfWare(Collections.singletonList(ware.getId()));
                Map<String, Long> wareStars = starCountOfWare.get(ware.getId());
                Integer stars = Math.toIntExact(wareStars != null ? wareStars.get("amount") : 0);
                int followed = 0;
                try {
                    followed = followMapper.selectByMap(MapUtil.of(
                            Pair.of("follower_id", UserIdUtil.getUserId()),
                            Pair.of("followed_id", ware.getId()),
                            Pair.of("follow_type", 2)
                    )).size();
                } catch (Exception ignored) {
                }

                BigDecimal price = ware.getPrice();
                if (ware.getSaleMethod().equals("拍卖")) {
                    price = goodsMapper.selectMaxPriceOfAuction(ware.getId());
                }

                Calendar endTime = Calendar.getInstance();
                endTime.setTimeInMillis(ware.getStartTime().getTime() + ware.getTime().getTime());

                GoodsDetail goodsDetail = GoodsDetail.builder()
                        .id(ware.getId().toString())
                        .nftId(nftId.toString())
                        .name(nft.getName())
                        .img(nft.getImg())
                        .attributes(nft.getAttribute())
                        .views(nft.getViews() + 1)
                        .stars(stars)
                        .focused(followed > 0)
                        .author(nft.getUsername())
                        .authorId(nft.getUserId().toString())
                        .owner(nft.getOwnerName())
                        .ownerId(nft.getOwnerId().toString())
                        .chainAddress(nft.getChainAddress())
                        .right(ware.getRight() == 1 ? "所有权" : ware.getRight() == 2 ? "版权" : "未知权利")
                        .startingPrice(ware.getPrice())
                        .currentPrice(price)
                        .endTime(endTime.getTime())
                        .description(nft.getDescription())
                        .status(convertStatus(ware.getStatus().toString()))
                        .saleMethod(ware.getSaleMethod())
                        .edition(ware.getEdition())
                        .build();

                result.add(goodsDetail);
            }
        }

        Assert.isTrue(nftMapper.updateById(Nft.builder()
                .id(nftId)
                .views(nft.getViews() + 1)
                .build()
        ) == 1, "更新浏览量失败");

        return result;
    }

    @Override
    public Object commentInfo(Long nftId) {
        List<Comment> comments = commentMapper.selectByMap(MapUtil.of(Pair.of("nft_id", nftId)));
        List<CommentInfo> ancestors = new ArrayList<>();
        HashMap<String, Object> ancestorsCountMap = new HashMap<>();
        if (comments != null && comments.size() > 0){
            Map<Long, Map<String, Long>> stars = goodsMapper.selectStarCountOfComments(comments.stream().map(Comment::getId).collect(Collectors.toList()));
            comments.forEach(c -> stars.putIfAbsent(c.getId(), MapUtil.of("amount", 0L)));
            List<CommentInfo> commentInfos = comments.stream().map(c -> CommentInfo.builder()
                    .id(c.getId())
                    .username(c.getUsername())
                    .portrait(c.getUserImg())
                    .time(c.getTime())
                    .stars(Math.toIntExact(stars.get(c.getId()).get("amount")))
                    .content(c.getComment())
                    .replyId(c.getReplyId())
                    .children(new ArrayList<>())
                    .build()
            ).collect(Collectors.toList());
            ancestors = commentInfos.stream().filter(c -> c.getReplyId() == null).collect(Collectors.toList());
            Assert.isTrue(commentInfos.removeAll(ancestors), "error happened when remove element from array");
            HashMap<Long, CommentInfo> commentInfoMap = new HashMap<>();
            ancestors.forEach(a -> commentInfoMap.put(a.getId(), a));
            sort(commentInfoMap, commentInfos);
            ancestors.sort(Comparator.comparing(CommentInfo::getTime));
        }
        ancestorsCountMap.put("ancestors", ancestors);
        ancestorsCountMap.put("count", ancestors.size());
        return ancestorsCountMap;
    }

    @Override
    public void newGoods(GoodsParameter parameter) {
        Assert.isTrue(nftMapper.selectCount(new QueryWrapper<Nft>().eq("id", parameter.getNftId())
                .eq("owner_id", UserIdUtil.getUserId())) > 0, "用户不拥有该nft");
        Calendar now = Calendar.getInstance();
        long userId = UserIdUtil.getUserId();
        String username = userMapper.selectById(userId).getName();

        Ware ware = Ware.builder()
                .nftId(parameter.getNftId())
                .uploaderId(UserIdUtil.getUserId())
                .uploaderName(username)
                .saleMethod(parameter.getSaleMethod())
                .goodsNum(parameter.getAmount())
                .right(parameter.getRight().equals("所有权") ? 1 : parameter.getRight().equals("版权") ? 2 : 0)
                .price(parameter.getPrice())
                .canDeal(parameter.getCanDeal())
                .royalty(parameter.getRoyalties())
                .privilege(parameter.getRightDetail())
                .startTime(now.getTime())
                .time(new Date(parameter.getEndTime().getTime() - now.getTimeInMillis()))
                .edition(parameter.getEdition())
                .status(0)
                .build();
        Assert.isTrue(wareMapper.insert(ware
        ) > 0, "商品上架失败");
        Assert.isTrue(userWareMapper.insert(UserWare.builder()
                .userId(UserIdUtil.getUserId())
                .wareId(ware.getId())
                .nftId(parameter.getNftId())
                .type(parameter.getRight().equals("所有权") ? 1 : parameter.getRight().equals("版权") ? 2 : 0)
                .status(1)
                .build()
        ) > 0, "商品上架失败");
    }

    @Override
    public void saleGoods(Long wareId) {
        Ware ware = wareMapper.selectById(wareId);
        long userId = UserIdUtil.getUserId();
        Assert.isTrue(ware.getUploaderId() == userId, "用户{}不拥有该商品", userId);

        Assert.isTrue(wareMapper.updateById(Ware.builder()
                .id(ware.getId())
                .status(1)
                .build()
        ) > 0, "上架失败");
    }

    @Override
    public void bidding(Long wareId, BigDecimal price) {
        Ware ware = wareMapper.selectById(wareId);
        Assert.isTrue(ware.getRight() == 1, "所有权之外的权利无法拍卖");

        long userId = UserIdUtil.getUserId();
        User user = userMapper.selectById(userId);
        Assert.isTrue(ware.getStatus() == 1, "商品{}未上架", wareId);
        Assert.isTrue(ware.getGoodsNum() > 0, "商品{}已售空", wareId);
        Assert.isTrue(ware.getUploaderId() != userId, "用户{}为商品拥有者", userId);

        Calendar now = Calendar.getInstance();
        Calendar deadline = Calendar.getInstance();
        deadline.setTimeInMillis(ware.getStartTime().getTime() + ware.getTime().getTime());
        Assert.isTrue(now.before(deadline), "商品{}已经超时下架", wareId);

        Assert.isTrue(user.getAssets().compareTo(price) >= 0, "用户没有足够资产");

        Offer offer = offerMapper.selectOne(new QueryWrapper<Offer>().eq("userId", userId).eq("wareId", wareId));
        if (offer == null) { // 未出价
            Assert.isTrue(offerMapper.insert(Offer.builder()
                    .userId(userId)
                    .wareId(wareId)
                    .price(price)
                    .build()
            ) > 0, "出价失败");
        } else {
            Assert.isTrue(offerMapper.updateById(Offer.builder()
                    .id(offer.getId())
                    .price(price)
                    .build()
            ) > 0, "出价更新失败");
        }
    }

    @Override
    public void offer(OfferInfo info) {
        long userId = UserIdUtil.getUserId();
        String username = userMapper.selectById(userId).getName();
        Ware ware = wareMapper.selectById(info.getWareId());
        Assert.notNull(ware, "找不到商品{}", info.getWareId());
        Assert.isTrue(ware.getCanDeal(), "商品不允许议价：", info.getWareId());
        Calendar now = Calendar.getInstance();
        if (info.getBargainId() != null) { // 原有议价
            Bargain bargain = bargainMapper.selectById(info.getBargainId());
            if (bargain.getBuyerId() == userId) { // 买家
                Assert.isTrue(bargainMapper.updateById(Bargain.builder()
                        .id(bargain.getId())
                        .buyerWords(info.getDescription())
                        .price(info.getPrice())
                        .status(3)
                        .build()
                ) > 0, "议价失败：{}", bargain.getId());
            } else { // 卖家
                Assert.isTrue(ware.getUploaderId() == userId, "用户不是买家或买家：", userId);
                Assert.isTrue(bargainMapper.updateById(Bargain.builder()
                        .id(bargain.getId())
                        .sellerWords(info.getDescription())
                        .price(info.getPrice())
                        .status(2)
                        .build()
                ) > 0, "议价失败：{}", bargain.getId());
            }
        } else {
            Assert.isTrue(bargainMapper.insert(Bargain.builder()
                    .wareId(info.getWareId())
                    .buyerId(userId)
                    .buyerName(username)
                    .buyerWords(info.getDescription())
                    .sellerWords(null)
                    .price(info.getPrice())
                    .status(1)
                    .time(now.getTime())
                    .build()
            ) > 0, "议价失败");
        }
    }

    @Override
    public void consume(String nftId) {
        long userId = UserIdUtil.getUserId();
        User user = userMapper.selectById(userId);

        Nft nft = nftMapper.selectById(nftId);
        Assert.notNull(nft, "查询不到nftId为{}的nft", nftId);
        Ware ware = wareMapper.selectOne(new QueryWrapper<Ware>().eq("nft_id", nftId));

        UserWare userWare = userWareMapper.selectOne(new QueryWrapper<UserWare>().eq("user_id", userId).eq("ware_id", ware.getId()).eq("type", ware.getRight()));
        // 用户未拥有此商品 或 用户曾经拥有但现在不拥有该商品
        Assert.isFalse(userWare != null && userWare.getStatus() == 1, "用户已经拥有该商品：{}", ware.getId());

        BigDecimal price = ware.getPrice();
        if (!price.equals(BigDecimal.ZERO)) {
            Assert.isTrue(user.getAssets().compareTo(price) >= 0, "用户没有足够资产，当前资产为：{}", user.getAssets());

            Assert.isTrue(userMapper.updateById(User.builder()
                    .id(user.getId())
                    .assets(user.getAssets().subtract(price))
                    .build()
            ) > 0, "支付失败");

            Assert.isTrue(userMapper.updateById(User.builder()
                    .id(ware.getUploaderId())
                    .assets(userMapper.selectById(ware.getUploaderId()).getAssets().add(price))
                    .build()) > 0, "支付失败");
        }

        if (userWare == null) {
            Assert.isTrue(userWareMapper.insert(UserWare.builder()
                    .userId(userId)
                    .wareId(ware.getId())
                    .nftId(ware.getNftId())
                    .type(ware.getRight())
                    .status(1)
                    .build()
            ) > 0, "购买失败");
        } else {
            Assert.isTrue(userWareMapper.updateById(UserWare.builder()
                    .status(1)
                    .build()
            ) > 0, "购买失败");
        }
    }

    @Override
    public void comment(Long nftId, Long commentId, String content) {
        long userId = UserIdUtil.getUserId();
        User user = userMapper.selectById(userId);

        if (commentId != null) { // 回复评论
            Comment comment = commentMapper.selectById(commentId);
            Assert.notNull(comment, "评论不存在：{}", commentId);
            Assert.isTrue(commentMapper.insert(Comment.builder()
                    .nftId(comment.getNftId())
                    .replyId(commentId)
                    .comment(content)
                    .time(Calendar.getInstance().getTime())
                    .userId(userId)
                    .username(user.getName())
                    .userImg(user.getImg())
                    .build()
            ) > 0, "插入评论失败");
        } else { // 回复nft
            Nft nft = nftMapper.selectById(nftId);
            Assert.notNull(nft, "找不到nft：", nftId);
            Assert.isTrue(commentMapper.insert(Comment.builder()
                    .nftId(nftId)
                    .comment(content)
                    .time(Calendar.getInstance().getTime())
                    .userId(userId)
                    .username(user.getName())
                    .userImg(user.getImg())
                    .build()
            ) > 0, "插入评论失败");
        }
    }

    @Override
    public Boolean isParentAuthor(Long nftId) {
        long userId = UserIdUtil.getUserId();
        User user = userMapper.selectById(userId);
        String address = user.getAddress();
        Result result = blockchainClient.isSeller(nftId.toString(), address);
        Assert.isTrue(result.getCode() == ResultCode.SUCCESS.getCode(), "请求接口失败");
        return (Boolean) result.getData();
    }

    @Override
    public void off(Long wareId) {
        Ware ware = wareMapper.selectById(wareId);
        Calendar deadline = Calendar.getInstance();
        deadline.setTimeInMillis(ware.getStartTime().getTime() + ware.getTime().getTime());
        Assert.isFalse(ware.getSaleMethod().equals("拍卖") && Calendar.getInstance().before(deadline), "拍卖中的商品无法下架，请联系管理员");
        Assert.notNull(ware, "找不到商品：{}", wareId);
        Assert.isTrue(wareMapper.updateById(Ware.builder()
                .id(wareId)
                .status(2)
                .build()
        ) > 0, "下架失败：", ware.getId());
    }

    @Override
    public void modify(ModifyGoodsParameter parameter) {
        Long wareId = parameter.getWareId();
        Ware ware = wareMapper.selectById(wareId);
        Assert.notNull(ware, "找不到商品：{}", wareId);
        Assert.isTrue(ware.getStatus() == 2, "非下架商品无法修改：{}，请联系管理员", wareId);
        Integer goodsNum = parameter.getGoodsNum();
        if (ware.getRight() == 1 || ware.getSaleMethod().equals("拍卖")) {
            goodsNum = null;
        }
        Integer resell = null;
        if (parameter.getResell() != null && ware.getResell() != 2) {
            resell = parameter.getResell();
        }
        Assert.isTrue(wareMapper.updateById(Ware.builder()
                .id(wareId)
                .price(parameter.getPrice())
                .goodsNum(goodsNum)
                .royalty(parameter.getRoyalty())
                .edition(parameter.getEdition())
                .resell(resell)
                .privilege(parameter.getPrivilege())
                .time(parameter.getTime())
                .build()
        ) > 0, "修改商品失败：{}", wareId);
    }

    @Override
    public PageInfo<BargainInfo> offerSearch(BargainSearch search) {
        //根据商品名称查找商品id
        List<Nft> nfts = nftMapper.selectList(new QueryWrapper<Nft>().like(search.getWareName() != null, "name", search.getWareName()));
        List<Long> nftIds = nfts.stream().map(Nft::getId).collect(Collectors.toList());
        List<Ware> wares = wareMapper.selectList(new QueryWrapper<Ware>().in("nft_id", nftIds));
        List<Long> wareIds = wares.stream().map(Ware::getId).collect(Collectors.toList());
        Map<Long, Nft> nftMap = new HashMap<>();
        nfts.forEach(n -> nftMap.put(n.getId(), n));
        Map<Long, Nft> wareMap = new HashMap<>();
        wares.forEach(w -> wareMap.put(w.getId(), nftMap.get(w.getNftId())));

        Page<BargainInfo> page = PageHelper.startPage(search.getLimit().getPageNum(), search.getLimit().getPageSize());
        List<BargainInfo> infos = bargainMapper.selectList(new QueryWrapper<Bargain>()
                        .ge(search.getPriceLow() != null, "price", search.getPriceLow())
                        .lt(search.getPriceHigh() != null, "price", search.getPriceHigh())
                        .in(search.getBargainId() != null && search.getBargainId().size() > 0, "id", search.getBargainId())
                        .in(search.getWareId() != null && search.getWareId().size() > 0, "ware_id", search.getWareId())
                        .in(search.getBuyerId() != null && search.getBuyerId().size() > 0, "buyer_id", search.getBuyerId())
                        .in(wareIds.size() > 0, "ware_id", wareIds))
                .stream().map(BargainInfo::new).collect(Collectors.toList());

        // 查找商品名称
        infos.forEach(i -> i.setWareName(wareMap.get(Long.parseLong(i.getWareId())).getName()));
        PageInfo<BargainInfo> pageInfo = PageInfo.of(page);
        pageInfo.setList(infos);
        return pageInfo;
    }

    private String convertStatus(String status) {
        switch (status) {
            case "0":
                return "未上架";
            case "1":
                return "上架";
            case "2":
                return "用户下架";
            case "3":
                return "审核下架";
            default:
                return "未知状态";
        }
    }

    private double getScore(ComprehensiveInfo current, ComprehensiveInfo standard) {
        Integer stars = current.getStars();
        Date startTime = current.getStartTime();

        Calendar now = Calendar.getInstance();
        long maxDuration = now.getTimeInMillis() - standard.getStartTime().getTime();
        if (standard.getStars() == 0 || maxDuration == 0) return 100;
        return Double.valueOf(stars) / standard.getStars() * 50
                + (now.getTimeInMillis() - startTime.getTime()) / (double) maxDuration * 50;
    }

    private void sort(Map<Long, CommentInfo> ancestors, List<CommentInfo> children) {
        while (children.size() != 0) {
            ArrayList<CommentInfo> toDelete = new ArrayList<>();
            for (CommentInfo child : children) {
                if (ancestors.containsKey(child.getReplyId())) {
                    ancestors.get(child.getReplyId()).getChildren().add(child);
                    toDelete.add(child);
                }
            }
            children.removeAll(toDelete);
            toDelete.forEach(e -> ancestors.put(e.getId(), e));
        }
    }
}
